《An Introduction To Redux》-redux简介

  乐弋

Redux ,尽管是目前前端界最火的库之一,但是还是有很多人对它有些困惑:它到底是个啥,用了它又有什么好处。

正如官方文档陈述一样,Redux是用来存放javascript 应用状态的容器,并且是可预测的。换句话说,它是一个应用程序的数据流架构,区别于像Underscore.js或者AngularJs 这样的js库和框架。

Redux诞生于2015年6月,作者Dan Abramov。他的灵感来源于Facebook的Flux 和 函数式编程语言Elm。因为简单、体积小(才2kb大小)和丰富的文档资料,它迅速在前端界流行起来。如果你想学习Redux的内部工作原理并且深入研究它,可以考虑看下 Dan 的免费课程。

Redux大部分是用来作为应用的状态管理器。总的来说,Redux将整个应用的状态保存在一个不可变的状态树(对象)上,就是不能直接改变它,必须通过一些方法(action&reducers)去告知它改变。下面我们将详细的去探讨这些。

与MVC、Flux的差异

首先说一下MVC:model-view-controller 模式, 大多数程序员都对此很熟悉,在MVC结构中,数据层(model)、展现层(view)和 逻辑层(controller)都很有明显的界限,各司其职。但它存在一个问题,特别是在大型应用中,就是数据流是双向的。这意味着一个变化(可能是用户的输入或者接口返回)可能会影响到整个应用的状态:比如双向绑定。这会导致我们很难知道状态是从那儿来的,调试都很为难。

再说下Flux, 它和Redux非常的相似。差别在于:

  • Flux可以有很多store来改变应用的状态,以事件方式去广播(告知)这些改变。而组件则可以订阅事件去同步最新的状态。Redux并没有这样的分发器(dispatcher),而Flux正是通过分发器去广播这些改变来注册回调事件
  • Flux衍生出来的有太多种类了,由此会对开发者们产生一些困惑和不一致性

Redux带来的好处

你或许会问“为啥我要用Redux ”, 好问题!(尼玛外国人写文章都是这样的吗),下面就列举下 Redux会给你下一个应用能带来的好处:

  • 可预测性
    只有唯一的数据源:唯一的store,这样就不会困惑于:这状态tm哪儿来的。只需要通过活动去同步状态就好。
  • 可维护性
    结果可预测和严谨的架构让代码维护更加简单。
  • 可组织性
    Redux有着严格的代码规范,这样出来的代码更加一致,方便团队去一起维护。
  • 服务端渲染
    这真的很有用,特别在初始化页面渲染的时候,这会提升用户体验和优化搜索引擎。直接通过服务器端创建store,然后传递给客户端。
  • 强大的开发者工具
    开发者通过它可以实时监控着整个应用的 活动到状态的改变。
  • 社区生态
    强大的社区支持,你学习或者使用任何库和框架都能得到各种各样的支持。
  • 可测试性
    编写可测试代码的第一条规则是写独立的小函数并且只做一件事。编写Redux代码,就是这样:小,纯 ,独!

函数式编程

曾经提到过,Redux是完全建立在函数式编程之上的。这些概念对于理解Redux如何工作以及为什么这样是非常重要的。下面我们回顾下函数式编程的基本概念:

  • 函数是第一等对象
  • 传参就是函数
  • 通过函数、递归和数组来控制流程
  • 比如采用用纯净函数、递归函数、 高阶函数、闭包和匿名函数
  • 比如采用辅助函数,比如map,filter和reduce.
  • 可以将函数连接在一起
  • 状态不可变
  • 不关注代码执行顺序

函数编程可以让我们写出更加纯净和模块化的代码。在流程和逻辑层上编写小而简单的代码,也让代码测试,维护和调试更加简单,同时这些小代码也都是可复用的,这样代码量也会下降,这的确很棒。这些函数不需要任何修改就可以复制粘贴到任何地方使用。函数在应用中都是隔离的,只会执行自己的代码,不会依赖其他模块,这样就减少了代码之间的耦合性。

你将会看到纯函数、匿名函数、闭包、高阶函数和方法链在函数式javascript的广泛使用。 Redux广泛的使用纯函数,理解它们也是非常重要的。

“纯函数”:会根据传给它的参数而返回一个全新的值。也就是说它不会修改现有的对象,而是返回一个全新的。它也不依赖传进来的状态,且只会返回和入参一样的结果。因此,它也是可预测的。

因为纯函数不会修改任何值,它也不会对整个作用域有任何影响或副作用,这也就意味着开发者只需要关心纯函数所返回出来的值。

Redux可以用在哪儿

大部分开发者会将React 和Redux 联系在一起,但实际上,它可以和任何一个js视图库 配合使用。比如 AngularJS,Vue.js,Polymer,Ember,Backbone.js 和 Meteor。 但Redux和React还是最普遍的组合。确保按正确的顺序去学习React: 这里我推荐前FaceBook员工Pete Hunt`s 的学习曲线,这十分适合刚开始学习React的开发者。不管是新手还是很有经验的前端开发者都会有“JS疲劳症”,所以用正确的方式以及正确的顺序来学习React和Redux 也是十分重要的。

Redux之所以比较惊艳的原因之一是因为它背后建立起来的生态:有关它的文章,教程,中间件,开发者工具和脚手架超级之多。就个人而言,我经常使用David Zukowski`s的脚手架,因为它包含了需要开发一个React应用的所有东西(React ,Redux和React router)。但同时我也要做个提醒:在学一个新框架(比如React和Redux)的时候还是不要使用脚手架或者新手包之类的,它会让你在使用的时候更加困惑,“我擦,为啥这样用!”会时常在里心里迸发出的一句话,因为你不知道它是怎么一起工作的。相反,我建议大家一步一步的从一个小的应用开始熟悉框架,最后再使用脚手架工具来提高开发效率。

Redux结构

Redux概念或许听起来比较复杂或者华而不实,但它其实是很简单的。记住它才2kb。Redux有3个组成部份:actions , store 和 reducers。

new_redux_data_flow_opt

看着上面的图 我们来一一看看每个部分的作用

  • Actions
    简而言之,actions(活动)其实就是事件。actions会将(由用户交互,内部事件或者表单提交)所产生的数据发送给store。并且store 只从actions获取信息。内部actions的结构是简单的json对象,它有一个type字段(通常是一个常量)来表述这个事件的类型,和需要发给store 的数据信息。

    1
    2
    3
    4
    {	
    type: LOGIN_FORM_SUBMIT,
    payload: {username: ‘alex’, password: ‘123456’}
    }

    Actions 是actions creators所生成,其实就是能返回actions的函数:

    1
    2
    3
    4
    5
    6
    function authUser(form) {
    return {
    type: LOGIN_FORM_SUBMIT,
    payload: form
    }
    }

    在应用中触发actions就更简单了,用dispatch方法就可以了,如下:

    dispatch(authUser(form));
    
  • Reducers
    我们已经讨论了在函数式javascript中的reducer是什么。 它是基于数组的reduce(累加器)方法:接收一个回调函数,可以将数组中的值合并变为一个值返回给你。在Redux里,reducers 是一个纯函数,它接收到一个应用state(状态)和一个action(活动),然后返回一个新的state(状态)。理解reducers是如何工作是非常重要的,因为他们占据了redux 中大部分工作。下面是一个非常简单的例子:

    1
    2
    3
    4
    5
    function handleAuth(state, action) {
    return Object.assign({}, state, {
    auth: action.payload
    });
    }

    对于一些更加复杂的应用,可以使用Redux自带的combineReducers()方法来把所有的reducers合并成一个 主reducer,同时保持每个reducers的独立性。这样维护起来也十分方便。
    如果状态树某些值改变了,Redux会生成一个新的对象,它不会改变之前的值,而是生成全新的值,这个很强大!如果你想它更有效,你可以试试增加一个 Immutable.js.的库。

    1
    2
    3
    4
    5
    const rootReducer = combineReducers({
    handleAuth: handleAuth,
    editProfile: editProfile,
    changePassword: changePassword
    });
  • Store
    Store顾名思义就是商店,它用来保存应用状态 同时 也提供一些辅助方法用来获取状态,分发活动和注册事件。整个应用状态只会保存在唯一的store树上。任何action只能通过reducers来返回新的状态。这样使得Redux变得简单和可预测!

    1
    2
    3
    4
    import { createStore } from ‘redux’;
    let store = createStore(rootReducer);
    let authInfo = {username: ‘alex’, password: ‘123456’};
    store.dispatch(authUser(authInfo));

开发者工具,实时监控 和 热加载

  • react-devtools 可以直接从chrome商店直接安装,当你需要调试的适合在你的审视台中就能看见.
  • redux-devtools则是一个插件,当你开启的时候会显示在你的页面右侧,你可以实时的监测到所有的状态变化,活动改变,甚至可以重置,撤销状态!就和使用git一样。
  • 通过热加载 你则可以改变代码的同时 实现 页面自动刷新~
    如下图(与此文章无关)
    7_21_2016_14_12_33
分享到